<?php
// +----------------------------------------------------------------------
// | sfadmin - Suifeng Administration
// +----------------------------------------------------------------------
// | Copyright (c) 2017-2020 http://suifeng.tech All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: suifeng <1787585212@qq.com>
// +----------------------------------------------------------------------

namespace suifeng;

use suifeng\helper\ClassHelper;
use suifeng\helper\StringHelper;

abstract class Model extends \think\Model
{
    /**
     * 时间戳处理。
     *
     * @var boolean
     */
    protected $autoWriteTimestamp = true;

    protected function trigger($event, &$params)
    {
        if (parent::trigger($event, $params) === false) {
            return false;
        }

        if (method_exists($this, '_' . $event)) {
            $result = call_user_func_array(array($this, '_' . $event), [ & $params]);
            if (false === $result) {
                return false;
            }
        }

        return true;
    }

    protected function _before_insert(&$data)
    {
        if ($this->autoWriteTimestamp) {
            if ($this->createTime && empty($this->data[$this->createTime])) {
                $this->data[$this->createTime] = $this->autoWriteTimestamp($this->createTime);
            }
            if ($this->updateTime && empty($this->data[$this->updateTime])) {
                $this->data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime);
            }
        }
    }

    public function getSchema()
    {
        return $this->getQuery()->getTableInfo('', 'schema');
    }

    public function initDefault()
    {
        $schema = $this->getSchema();
        foreach (array_keys($schema) as $field) {
            $default = $schema[$field]['default'];

            if ($default === null && !$schema[$field]['autoinc'] && !$schema[$field]['notnull']) {
                if (strpos($schema[$field]['type'], 'int') !== false) {
                    $default = 0;
                } else if (strpos($schema[$field]['type'], 'char') !== false) {
                    $default = '';
                } else if (strpos($schema[$field]['type'], 'text') !== false) {
                    $default = '';
                }
            }

            $this->setAttr($field, $default);
        }
        return $this;
    }

    public function acceptData($data)
    {
        $schema = $this->getSchema();
        foreach (array_keys($schema) as $field) {
            if (array_key_exists($field, $data)) {
                if (is_array($data[$field])) {
                    $this->setAttr($field, $data[$field] ? json_encode($data[$field]) : '');
                } else {
                    $this->setAttr($field, $data[$field]);
                }
            }
        }
        return $this;
    }

    public function acceptPost()
    {
        return $this->acceptData(request()->post());
    }





    /**
     * 数据类型与控件类型的对应关系。
     *
     * @var array
     */
    protected $data_type_map = array(
        'integer'       => 'number',
    );

    /**
     * 不可以修改的字段名称列表。
     *
     * @var array
     */
    protected $uneditable_field_names = array(
        'id', 'create_time', 'update_time',
    );

    /**
     * 缓存的模型字段。
     *
     * @var unknown
     */
    protected $cache_model_fields = null;

    /**
     * 返回模型属性。
     *
     * @param unknown $name
     * @param unknown $default
     * @return string
     */
    public function get_model_property($name, $default = null)
    {
        $method_name = '_' . $name;
        if (method_exists($this, $method_name)) {
            if (($result = $this->$method_name()) !== null) {
                return $result;
            }
        }

        $method_name = '_model_' . $name;
        if (method_exists($this, $method_name)) {
            if (($result = $this->$method_name()) !== null) {
                return $result;
            }
        }

        return $default;
    }

    /**
     * 返回模型对象标题。
     *
     * @return unknown|string
     */
    protected function _model_title()
    {
        if (isset($this->model_title) && $this->model_title) {
            return $this->model_title;
        }

        return StringHelper::friendly_text($this->name);
    }

    /**
     * 返回模型字段列表。
     *
     * @return array
     */
    protected function _model_fields()
    {
        // 本方法会初始化模型对象所有的字段属性。
        // 这是一个复杂的过程，所以会通过实例变量做一下缓存。

        if ($this->cache_model_fields !== null) {
            return $this->cache_model_fields;
        }

        $this->cache_model_fields = array();
        $model_fields = isset($this->model_fields) ? $this->model_fields : array();

        foreach ($model_fields as $field_name => $field_info) {
            $field_info['field'] = $field_name;

            if (empty($field_info['dbtype'])) {
                $field_info['dbtype'] = 'string';
            }

//             if (! isset($field_info['default'])) {
//                 $field_info['default'] = ClassUtil::default_value($field_info['dbtype']);
//             }

            if (empty($field_info['title'])) {
                if (isset($field_info['label'])) {
                    $field_info['title'] = $field_info['label'];
                } else {
                    $field_info['title'] = StringHelper::friendly_text($field_name);
                }
            }

            if (empty($field_info['label'])) {
                if (isset($field_info['title'])) {
                    $field_info['label'] = $field_info['title'];
                } else {
                    $field_info['label'] = StringHelper::friendly_text($field_name);
                }
            }

            if (empty($field_info['control'])) {
                if (isset($field_info['display'])) {
                    $field_info['control'] = $field_info['display'];
                } else if (isset($field_info['editable']) && $field_info['editable'] === true) {
                    $field_info['control'] = 'text';
                }
            }

            if (empty($field_info['column'])) {
                if (isset($field_info['display'])) {
                    $field_info['column'] = $field_info['display'];
                } else if (isset($field_info['listable']) && $field_info['listable'] === true) {
                    $field_info['column'] = 'text';
                }
            }

//             if (empty($field_info['control'])) {
//                 if (isset($field_info['display'])) {
//                     $field_info['control'] = $field_info['display'];
//                 } else if (isset($field_info['identity']) && $field_info['identity']) {
//                     $field_info['control'] = 'hidden';
//                 } else if (in_array($field_name, $this->uneditable_field_names)) {
//                     $field_info['control'] = 'hidden';
//                 } else if (array_key_exists($field_info['dbtype'], $this->data_type_map)) {
//                     $field_info['control'] = $this->data_type_map[$field_info['dbtype']];
//                 } else {
//                     $field_info['control'] = 'text';
//                 }
//             }

//             if (empty($field_info['column'])) {
//                 if (isset($field_info['display'])) {
//                     $field_info['column'] = $field_info['display'];
//                 } else {
//                     $field_info['column'] = 'text';
//                 }
//             }

            $field_info['rules'] = $this->_init_field_rules($field_name, $field_info);
            $this->cache_model_fields[$field_name] = $field_info;
        }

        return $this->cache_model_fields;
    }

    /**
     * 初始化字段验证规则。
     *
     * @param unknown $field_name
     * @param unknown $field_info
     * @return array
     */
    private function _init_field_rules($field_name, $field_info)
    {
        $field_rules = $default_rules = array();

        foreach (isset($field_info['rules']) ? $field_info['rules'] : [] as $type => $config) {
            if (is_string($config)) {
                if (is_int($type)) {
                    $config = ['rule' => $config];
                } else {
                    $config = ['rule' => $type, 'message' => $config];
                }
            } else {
                if (is_string($type)) {
                    $config['rule'] = $type;
                }
            }
            $field_rules[] = $config;
        }

        if (isset($field_info['required']) && $field_info['required'] === true && !$this->_check_rule_exists($field_rules, 'required')) {
            $default_rules[] = ['rule' => 'required'];
        }

        if ($field_info['dbtype'] == 'string' && isset($field_info['length']) && $field_info['length'] > 0 && !$this->_check_rule_exists($field_rules, 'length')) {
            $default_rules[] = ['rule' => 'length', 'max' => intval($field_info['length'])];
        }

        if (isset($field_info['unique']) && $field_info['unique'] === true && !$this->_check_rule_exists($field_rules, 'unique')) {
            $default_rules[] = ['rule' => 'unique'];
        }

        return array_merge($default_rules, $field_rules);
    }

    /**
     * 检查指定的rule是否存在。
     *
     * @param unknown $rule_list
     * @param unknown $check_rule
     * @return boolean
     */
    private function _check_rule_exists($rule_list, $check_rule)
    {
        foreach ($rule_list as $rule_config) {
            if (isset($rule_config['rule']) && $rule_config['rule'] == $check_rule) {
                return true;
            }
        }
        return false;
    }

    /**
     * 返回主KEY字段。
     *
     * @return array
     */
    protected function _model_key_field()
    {
        return $this->getPk();
    }

    /**
     * 返回可搜索字段列表。
     *
     * @return array
     */
    protected function _model_avail_search_fields()
    {
        if (isset($this->avail_search_fields) && $this->avail_search_fields) {
            return $this->avail_search_fields;
        }

        // 查询searchable字段
        $search_fields = array();

        foreach ($this->_model_fields() as $name => $field) {
            if (isset($field['searchable']) && $field['searchable'] === true) {
                $search_fields[] = $name;
            }
        }

        return $search_fields;
    }

    /**
     * 返回可过滤字段列表。
     *
     * @return array
     */
    protected function _model_avail_filter_fields()
    {
        if (isset($this->avail_filter_fields) && $this->avail_filter_fields) {
            return $this->avail_filter_fields;
        }

        // 查询sortable字段
        $filter_fields = array();

        foreach ($this->_model_fields() as $name => $field) {
            if (isset($field['filterable']) && $field['filterable'] === true) {
                $filter_fields[] = $name;
            }
        }

        return $filter_fields;
    }

    /**
     * 返回可排序字段列表。
     *
     * @return array
     */
    protected function _model_avail_sort_fields()
    {
        if (isset($this->avail_sort_fields) && $this->avail_sort_fields) {
            return $this->avail_sort_fields;
        }

        // 查询sortable字段
        $sort_fields = array();

        foreach ($this->_model_fields() as $name => $field) {
            if (isset($field['sortable']) && $field['sortable'] === true) {
                $sort_fields[] = $name;
            }
        }

        return $sort_fields;
    }

    /**
     * 返回是否允许搜索？
     *
     * @return boolean
     */
    protected function _model_enable_search()
    {
        if (isset($this->enable_search)) {
            return $this->enable_search;
        } else {
            $search_fields = $this->_model_avail_search_fields();
            return !empty($search_fields);
        }
    }

    /**
     * 返回是否允许排序？
     *
     * @return boolean
     */
    protected function _model_enable_sort()
    {
        if (isset($this->enable_sort)) {
            return $this->enable_sort;
        } else {
            $sort_fields = $this->_model_avail_sort_fields();
            return !empty($sort_fields);
        }
    }

    /**
     * 返回是否允许过滤？
     *
     * @return boolean
     */
    protected function _model_enable_filter()
    {
        if (isset($this->enable_filter)) {
            return $this->enable_filter;
        } else {
            $filter_fields = $this->_model_avail_filter_fields();
            return !empty($filter_fields);
        }
    }

    /**
     * 返回是否允许分页？
     *
     * @return boolean
     */
    protected function _model_enable_page()
    {
        if (isset($this->enable_page)) {
            return $this->enable_page;
        } else {
            return true;
        }
    }

    /**
     * 返回是否允许选择？
     *
     * @return boolean
     */
    protected function _model_enable_select()
    {
        if (isset($this->enable_select)) {
            return $this->enable_select;
        } else {
            return true;
        }
    }

    /**
     * 返回默认排序。
     *
     * @return null|string
     */
    protected function _model_default_sort()
    {
        if (isset($this->default_sort) && $this->default_sort) {
            return $this->default_sort;
        } else {
            return null;
        }
    }

    /**
     * 返回默认排序字段。
     *
     * @return null|string
     */
    protected function _model_default_sort_field()
    {
        $default_sort = $this->_model_default_sort();
        if (empty($default_sort)) {
            return null;
        }

        // 多个排序字段，处理不了
        if (strpos($default_sort, ',') !== false) {
            return null;
        }

        list($field, $order) = exp(' ', $default_sort);
        return trim($field);
    }

    /**
     * 返回默认排序顺序。
     *
     * @return null|string
     */
    protected function _model_default_sort_order()
    {
        $default_sort = $this->_model_default_sort();
        if (empty($default_sort)) {
            return null;
        }

        // 多个排序字段，处理不了
        if (strpos($default_sort, ',') !== false) {
            return null;
        }

        list($field, $order) = exp(' ', $default_sort, 2);
        return empty($order) ? 'asc' : trim($order);
    }

    /**
     * 返回默认页面大小。
     *
     * @return null|string
     */
    protected function _model_default_page_size()
    {
        if (isset($this->default_page_size) && $this->default_page_size) {
            return $this->default_page_size;
        } else {
            return config('ADMIN_PAGE_ROWS');
        }
    }

    /**
     * 返回默认数据。
     *
     * @return null|string
     */
    protected function _model_default_data_array()
    {
        $default_data = array();
        foreach ($this->_model_fields() as $name => $field) {
            if (isset($field['default'])) {
                $default_data[$name] = $field['default'];
            } else {
                if (isset($field['identity']) && $field['identity'] === true) {
                    $default_data[$name] = null;
                } else {
                    $default_data[$name] = ClassHelper::default_value($field['dbtype']);
                }
            }
        }
        return $default_data;
    }

    /**
     * 返回列表字段列表。
     *
     * @return array
     */
    protected function _model_list_fields()
    {
        if (isset($this->list_fields) && $this->list_fields) {
            return $this->list_fields;
        }

        // 查询listable字段
        $list_fields = array();

        foreach ($this->_model_fields() as $name => $field) {
            if (isset($field['listable']) && $field['listable'] === true) {
                $list_fields[] = $name;
            }
        }

        return $list_fields;
    }

    /**
     * 返回表单字段列表。
     *
     * @return array
     */
    protected function _model_form_fields()
    {
        if (isset($this->form_fields) && $this->form_fields) {
            return $this->form_fields;
        }

        // 查询editable字段
        $form_fields = array();

        foreach ($this->_model_fields() as $name => $field) {
            if (isset($field['editable']) && $field['editable'] === true) {
                $form_fields[] = $name;
//             } else if (! isset($field['editable'])) {
//                 if (isset($field['control'])) {
//                     $form_fields[] = $name;
//                 }
            }
        }

        return $form_fields;
    }

    /**
     * 返回表单字段布局。
     *
     * @return array
     */
    protected function _model_form_layout()
    {
        if (isset($this->form_layout) && $this->form_layout) {
            return $this->form_layout;
        }

        // 没有设置form_layout，就直接返回null，让表单对象自动创建。
        return null;
    }

    /**
     * 返回列表行操作列表。
     *
     * @return null|string
     */
    protected function _model_list_actions()
    {
        if (isset($this->list_actions) && $this->list_actions) {
            return $this->list_actions;
        } else {
            return ['modify', 'delete'];
        }
    }

    /**
     * 返回列表按钮列表。
     *
     * @return null|string
     */
    protected function _model_list_buttons()
    {
        if (isset($this->list_buttons) && $this->list_buttons) {
            return $this->list_buttons;
        } else {
            return ['create'];
        }
    }


    /**
     * 显示对象的摘要信息。
     *
     * @return string
     */
    public function summary_info($data)
    {
        if (empty($this->summary_format)) {
            return null;
        }

        return \suifeng\helper\StringHelper::replace_token($this->summary_format, $data);
    }

//  public function save_or_update($data)
//  {
//      if (isset($data[$this->getPk()])) {
//             $pk = empty($data[$this->getPk()]);
//         } else {
//             $pk = null;
//         }

//         if ($pk) {
//             $query = $this->_create_query(null, null);
//             $query->where(array($this->getPk(), $pk));
//             return $query->update($data);
//         } else {
//             $query = $this->_create_query(null, null);
//             return $query->insertGetId($data);
//         }
//  }

//  public function fetch_one($where)
//  {
//      if (is_array($where)) {
//          $query = $this->_create_query($where, null);
//      } else {
//          $query = $this->_create_query([$this->getPk(), $where], null);
//      }

//      $query->limit(0, 1);
//      $rows = $this->_fetch_rows($query);

//      if ($rows) {
//          $this->_after_fetch_row($rows[0]);
//          return $rows[0];
//      } else {
//          return null;
//      }
//  }

//  public function fetch_list($where = null, $order = null)
//  {
//      $where = array_merge($this->_model_default_where(), (array) $where);
//      $query = $this->_create_query($where, $order);
//      $rows = $this->_fetch_rows($query);
//      foreach ($rows as &$row) {
//          $this->_after_fetch_row($row);
//      }
//      return $rows;
//  }

//  public function fetch_page($page, $length, $where = null, $order = null)
//  {
//      $where = array_merge($this->_model_default_where(), (array) $where);
//      $query = $this->_create_query($where, $order);
//      $query->limit(($page - 1) * $length, $length);
//      return $this->_fetch_rows($query);
//  }

//  public function fetch_count($where = null, $order = null)
//  {
//      $where = array_merge($this->_model_default_where(), (array) $where);
//      $query = $this->_create_query($where, $order);
//      return $query->count();
//  }

//  public function fetch_pair($key_field, $value_field, $where = null, $order = null)
//  {
//      $where = array_merge($this->_model_default_where(), (array) $where);
//      $query = $this->_create_query($where, $order);
//      $query->field(array($key_field, $value_field));

//         $result = array();
//         foreach ($this->_fetch_rows($query) as $row) {
//             $result[$row[$key_field]] = $row[$value_field];
//         }

//         return $result;
//  }

//  public function fetch_field($field_name, $where = null, $order = null)
//  {
//      $where = array_merge($this->_model_default_where(), (array) $where);
//      $query = $this->_create_query($where, $order);
//      $query->field(array($field_name));

//      $result = array();
//      foreach ($this->_fetch_rows($query) as $row) {
//          $result[] = $row[$field_name];
//      }

//      return $result;
//  }



//  public function fetch_list($where = null, $order = null, $page = null, $length = null)
//  {
//      $query = $this->_create_query($where, $order, $page, $length);

//      $list = $this->select();
//      $rows = array();

//      foreach ($list as $row) {
//          $row = $row->getData();
//          $this->_after_fetch_row($row);
//          $rows[] = $row;
//      }

//      return $rows;
//  }

//  protected function _create_query($where, $order, $page, $length)
//  {
//      $model = new static();
//      $query = $model->db();

//      if ($where) {
//          $query->where($where);
//      }

//      if ($order) {
//          $query->order($order);
//      }

//      if ($page && $length) {
//          $query->page($page, $length);
//      }

//      return $query;
//  }

//  protected function _after_fetch_row(&$row) {}
}